#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "soc.h"
#include "drv_dpu.h"
#include "i2c_base.h"
#include "i2c_aw99703.h"
#include "i2c_sgm3804.h"
#include "lcd.h"
#include "drv_delay.h"
#include "lcd_para_55.h"
#include "lcd_para_8.h"

static mipi_dsi_host_handle_t mipi_dsi_host_handle;
static mipi_dsi_host_config_t g_mipi_dsi_host_cfg;

static EM_LCD_TYPE g_lcd_type;
static char g_typ_str[MIPI_LCD_360_NUM][32] = {"mipi lcd 5.5 inch hx8394f", \
                           "mipi lcd 8 inch jd9365"};


#define LCD_READ_ID3_CMD 0xDC
#define LCD_READ_ID2_CMD 0xDB
#define LCD_READ_ID1_CMD 0xDA
#define LCD_5_5_ID3		 0x31
#define LCD_8_ID3		 0x32

static void mipi_lcd_bringup(void)
{
    dw_mipi_host_short_packet_write(mipi_dsi_host_handle, 0x5, 0x11, 0x00);
    mdelay(120);
    dw_mipi_host_short_packet_write(mipi_dsi_host_handle, 0x5, 0x29, 0x00);
    mdelay(40);

    csi_dsi_host_enter_video_mode(mipi_dsi_host_handle, DSI_HOST_VIDEO_PATTERN_DISABEL);
}

#if 0
static int lcd_get_type(EM_LCD_TYPE *lcd_type)
{
	int ret3 = 0;int ret2 = 0;int ret1 = 0;
    int ret6 = 0;int ret5 = 0;int ret4 = 0;
 	uint32_t read_id3;			
    uint32_t read_id2;
    uint32_t read_id1;
 	uint32_t read_id6;			
    uint32_t read_id5;
    uint32_t read_id4;

    
	ret3 = dw_mipi_host_short_packet_read(mipi_dsi_host_handle, 0x04,
		LCD_READ_ID3_CMD, 0, &read_id3);

    ret2 = dw_mipi_host_short_packet_read(mipi_dsi_host_handle, 0x04,
        LCD_READ_ID2_CMD, 0, &read_id2);

    ret1 = dw_mipi_host_short_packet_read(mipi_dsi_host_handle, 0x04,
        LCD_READ_ID1_CMD, 0, &read_id1);

    
    ret6 = dw_mipi_host_short_packet_read(mipi_dsi_host_handle, 0x06,
        LCD_READ_ID3_CMD, 0, &read_id6);
    
    ret5 = dw_mipi_host_short_packet_read(mipi_dsi_host_handle, 0x06,
        LCD_READ_ID2_CMD, 0, &read_id5);
    
    ret4 = dw_mipi_host_short_packet_read(mipi_dsi_host_handle, 0x06,
        LCD_READ_ID1_CMD, 0, &read_id4);
    


	if (ret3&&ret2&&ret1&&ret6&&ret5&&ret4) {
		printf("%s %d: read id err.\r\n", __func__, __LINE__);
		return -1;
	} else {
		printf("ID3/2/1: 0x%x 0x%x 0x%x\r\n", read_id3,read_id2,read_id1);
		printf("ID6/5/4: 0x%x 0x%x 0x%x\r\n", read_id6,read_id5,read_id4);
		if ( (read_id3 == LCD_8_ID3) || (read_id2 == LCD_8_ID3) || (read_id1 == LCD_8_ID3) || (read_id6 == LCD_8_ID3) || (read_id5 == LCD_8_ID3) || (read_id4 == LCD_8_ID3) )
			*lcd_type = MIPI_LCD_360_8;
		else if ( (read_id3 == LCD_5_5_ID3) || (read_id2 == LCD_5_5_ID3) || (read_id1 == LCD_5_5_ID3) || (read_id6 == LCD_5_5_ID3) || (read_id5 == LCD_5_5_ID3) || (read_id4 == LCD_5_5_ID3)  )
			*lcd_type = MIPI_LCD_360_55;
		else {
			printf("ID3 err, default 5.5 inch.\r\n");
			*lcd_type = MIPI_LCD_360_55;
		}
	}

	return 0;
}


static int mipi_dsi_host_init(void)
{
    int32_t ret;

    mipi_dsi_host_handle = csi_mipi_dsi_host_initialize(0, NULL, NULL);
	/* just for low speen, read lcd id */
	memcpy(&g_mipi_dsi_host_cfg, &g_lcd_55_hx8394_cfg, sizeof(mipi_dsi_host_config_t));
	ret = csi_mipi_dsi_host_start(mipi_dsi_host_handle, &g_mipi_dsi_host_cfg);
    return ret;
}


static int mipi_dsi_host_start(void)
{
    int32_t ret;

	ret = csi_mipi_dsi_host_start(mipi_dsi_host_handle, &g_mipi_dsi_host_cfg);
    return ret;
}
#endif

static int mipi_dsi_host_config(void)
{
    int32_t ret;

    mipi_dsi_host_handle = csi_mipi_dsi_host_initialize(0, NULL, NULL);
    ret = csi_mipi_dsi_host_start(mipi_dsi_host_handle, &g_mipi_dsi_host_cfg);
    return ret;
}


#define MIPI_LCD_RESET_AOGPIO   4
#define AOGPIO_OUTPUT           1
#define AOGPIO_INPUT            0

#if 0
static void aogpio_dir(uint8_t pin, uint8_t dir)
{
    uint32_t reg;

    reg = inl(0xfff02004);
    reg &= ~(1 << pin);
    reg |= (dir << pin);
    outl(reg, 0xfff02004);
}
static void aogpio_wr(uint8_t pin, uint8_t val)
{
    uint32_t reg;

    reg = inl(0xfff02000);
    reg &= ~(1 << pin);
    reg |= (val << pin);
    outl(reg, 0xfff02000);        
}
#endif
int lcd_get_cfg(EM_LCD_TYPE lcd_type, mipi_dsi_host_config_t *cfg)
{
    int ret = 0;
    
    switch(lcd_type) {
    case MIPI_LCD_360_55:
        memcpy(cfg, &g_lcd_55_hx8394_cfg, sizeof(mipi_dsi_host_config_t));
        break;
    case MIPI_LCD_360_8:
        memcpy(cfg, &g_lcd_8_jd9365_cfg, sizeof(mipi_dsi_host_config_t));        
        break;
    default:
        printf("360 lcd type error.\r\n");
        ret = -1;
        break;
    }

    return ret;
}

int lcd_init(EM_LCD_TYPE *lcd_type)
{
    int ret;
    uint8_t bl_ch_msk;
        
	if (lcd_type == NULL) {
        printf("%s %d: input pera err.\r\n", __func__, __LINE__);
        return -1;				
	}
	//mipi_dsi_host_init();
    g_lcd_type = MIPI_LCD_360_55;
	*lcd_type = g_lcd_type;
    ret = lcd_get_cfg(g_lcd_type, &g_mipi_dsi_host_cfg);
    if (ret )
        return ret;
    
    ret = lcd_i2c_int();
    if (ret) {
        printf("%s i2c init err.\r\n", &g_typ_str[g_lcd_type][0]);
        return ret;
    }
#if 0
    aogpio_dir(MIPI_LCD_RESET_AOGPIO, AOGPIO_OUTPUT);
    aogpio_wr(MIPI_LCD_RESET_AOGPIO, 1);
    mdelay(10);
    aogpio_wr(MIPI_LCD_RESET_AOGPIO, 0);
    mdelay(50);
    aogpio_wr(MIPI_LCD_RESET_AOGPIO, 1);
    mdelay(10);
#endif 

#if 0
    ret = sgm3804_init();
    if (ret) {
        printf("%s SGM3804 init on err.\r\n", &g_typ_str[g_lcd_type][0]);
        return ret;
    }
#endif
    if (g_lcd_type == MIPI_LCD_360_55)
        bl_ch_msk = AW99703_BL_CH1 | AW99703_BL_CH2;
    else
        bl_ch_msk = AW99703_BL_CH1 | AW99703_BL_CH2 | AW99703_BL_CH3;
    ret = aw99703_init(AW99703_MAX_BL_CODE, bl_ch_msk);
    if (ret) {
        printf("%s aw99703 init err.\r\n", &g_typ_str[g_lcd_type][0]); 
        return ret;
    }
    
    mipi_dsi_host_config();
    mipi_lcd_bringup();

    printf("%s init success.\r\n", g_typ_str[g_lcd_type]);

    return 0;
}


int lcd_backlight(int backlight_code)
{
    return aw99703_adj_bklgt(backlight_code);
}

